'''
项目名称：产业园区管理运营平台
文件名称：测试数据生成脚本
@Author: 王旭
@Contact: 1643959780@qq.com
@Created: 2023/07/15
@Version: V1.1
@LastModified: 2025/06/28

@Description:
本脚本用于为产业园区管理运营平台生成测试数据，支持灵活配置各类数据的生成规则。
主要功能包括：
1. 创建用户账号：包括管理员、园区员工、企业员工等不同角色的用户
2. 创建企业信息：自动生成5个企业公司和1个物业公司
3. 创建部门结构：为每个公司创建多个部门
4. 创建员工档案：每个部门至少5位员工（包含经理），根据配置生成不同类型的员工
5. 创建访客记录：生成至少20位园区访客数据，包含不同访问状态

@Modifications:
- V1.0 (2023/06/28): 初始版本，实现基本的数据生成功能
- V1.1 (2025/06/28): 重构数据生成逻辑，统一企业、部门、员工和访客的生成方式，
  简化配置项，提高数据一致性，增强访客状态处理逻辑
'''

import os
import sys
import django
import random
import datetime
from pypinyin import pinyin, Style

# --- Start: 动态添加项目根目录到 sys.path ---
# 获取当前脚本文件(init_business.py)的绝对路径
current_script_path = os.path.abspath(__file__)
# 获取脚本所在的目录 (script/)
script_dir = os.path.dirname(current_script_path)
# 获取项目根目录 (back/)，即 script 目录的上级目录
project_root = os.path.dirname(script_dir)
# 将项目根目录添加到 Python 模块搜索路径中
sys.path.append(project_root)
# --- End: 动态添加项目根目录到 sys.path ---

from django.utils import timezone

# 设置Django环境
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'smartpark.settings')
django.setup()

# 导入模型
from django.db import transaction, IntegrityError
from users.models import User, ParkEmployeeProfile, Company, CompanyEmployeeProfile, Department, Visitor
from assets.models import Vehicle

# 配置参数
CONFIG = {
    "companies": {
        "count": 5,  # 企业公司数量
        "types": ["科技企业", "制造企业", "服务企业", "贸易企业", "金融企业"]
    },
    "property_company": {
        "name": "智慧物业管理有限公司",
        "type": "物业公司",
        "departments": ["管理部", "维修部", "保洁部", "后勤部", "安保部"]
    },
    "company_departments": ["研发部", "市场部", "财务部", "人力资源部", "行政部", "销售部"],
    "employees_per_department": 5,  # 每个部门的员工数量（包括经理）
    "visitors": {
        "count": 50
    },
    "vehicles": {
        "company_employee_ratio": 0.4,  # 40%的企业员工有车
        "visitor_ratio": 0.2,  # 20%的访客有车
        "brands_models": {
            "大众": ["帕萨特", "迈腾", "高尔夫", "途观L"],
            "丰田": ["凯美瑞", "卡罗拉", "汉兰达", "RAV4荣放"],
            "本田": ["雅阁", "思域", "CR-V"],
            "奥迪": ["A4L", "A6L", "Q5L"],
            "宝马": ["3系", "5系", "X3"],
            "奔驰": ["C级", "E级", "GLC"],
            "比亚迪": ["汉", "唐", "宋PLUS", "海豚"],
            "特斯拉": ["Model 3", "Model Y"]
        },
        "colors": ["黑色", "白色", "银灰色", "蓝色", "红色", "香槟金"],
        "types": ["小轿车", "SUV"]
    },
    "password": "12345"  # 默认密码
}

# 中文姓名生成
SURNAMES = ["张", "王", "李", "赵", "陈", "刘", "杨", "黄", "周", "吴", "郑", "孙", "马", "朱", "胡", "林", "郭", "何", "高", "罗"]
NAMES = ["伟", "芳", "娜", "秀英", "敏", "静", "丽", "强", "磊", "军", "洋", "勇", "艳", "杰", "娟", "涛", "明", "超", "秀兰", 
         "霞", "平", "刚", "桂英", "建", "国", "华", "文", "斌", "玉", "萍", "宇", "辉", "宁", "亮", "燕", "红", "健", "云"]

# 公司名称生成
COMPANY_PREFIXES = ["智慧", "创新", "科技", "未来", "星辰", "领航", "卓越", "鼎盛", "宏远", "博达", "盛世", "华信", "鑫源", "恒基", "瑞丰"]
COMPANY_SUFFIXES = ["科技有限公司", "信息技术有限公司", "电子科技有限公司", "网络科技有限公司", "智能科技有限公司", 
                   "实业有限公司", "集团有限公司", "股份有限公司", "投资有限公司", "贸易有限公司"]

PROVINCES = ["京", "津", "冀", "晋", "蒙", "辽", "吉", "黑", "沪", "苏", "浙", "皖", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "渝", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新"]

# 工具函数
def generate_plate_number():
    """生成随机中国车牌号"""
    province = random.choice(PROVINCES)
    letter = random.choice('ABCDEFGHJKLMNPQRSTUVWXYZ')  # I 和 O 通常不用
    suffix = ''.join(random.choice('0123456789ABCDEFGHJKLMNPQRSTUVWXYZ') for _ in range(5))
    return f"{province}{letter}{suffix}"

def generate_name():
    """生成随机中文姓名"""
    return random.choice(SURNAMES) + random.choice(NAMES)

def generate_phone():
    """生成随机手机号"""
    prefix = random.choice(["138", "139", "135", "136", "137", "150", "151", "152", "158", "159", "188", "187"])
    suffix = ''.join(random.choice('0123456789') for _ in range(8))
    return prefix + suffix

def generate_email(username):
    """根据用户名生成邮箱"""
    domains = ["example.com", "test.com", "company.cn", "mail.org", "work.net", "smart.tech", "park.com"]
    return f"{username}@{random.choice(domains)}"

def generate_id_card():
    """生成随机身份证号"""
    # 简化的身份证号生成，实际应用中可能需要更复杂的逻辑
    prefix = random.choice(["110101", "310101", "440101", "510101", "610101", "330101", "320101", "420101"])
    birth = f"{random.randint(1970, 2000)}{random.randint(1, 12):02d}{random.randint(1, 28):02d}"
    suffix = ''.join(random.choice('0123456789') for _ in range(4))
    return prefix + birth + suffix

def generate_company_name(company_type):
    """根据公司类型生成公司名称"""
    if company_type == "物业公司":
        return CONFIG["property_company"]["name"]
    
    prefix = random.choice(COMPANY_PREFIXES)
    
    if company_type == "科技企业":
        return prefix + random.choice(["科技", "智能", "数码", "网络", "软件"]) + random.choice(COMPANY_SUFFIXES[:5])
    elif company_type == "制造企业":
        return prefix + random.choice(["机械", "电子", "精密", "工业", "制造"]) + random.choice(COMPANY_SUFFIXES[5:7])
    elif company_type == "服务企业":
        return prefix + random.choice(["服务", "咨询", "管理", "人力", "教育"]) + random.choice(COMPANY_SUFFIXES[5:8])
    elif company_type == "贸易企业":
        return prefix + random.choice(["贸易", "进出口", "商贸", "物流", "供应链"]) + random.choice(COMPANY_SUFFIXES[8:])
    elif company_type == "金融企业":
        return prefix + random.choice(["金融", "投资", "资本", "财富", "证券"]) + random.choice(COMPANY_SUFFIXES[7:])
    else:
        return prefix + random.choice(COMPANY_SUFFIXES)

def create_single_vehicle(user=None, visitor=None):
    """为一个用户或访客创建一条车辆记录"""
    plate_number = generate_plate_number()
    while Vehicle.objects.filter(plate_number=plate_number).exists():
        plate_number = generate_plate_number()
    
    brand = random.choice(list(CONFIG["vehicles"]["brands_models"].keys()))
    model = random.choice(CONFIG["vehicles"]["brands_models"][brand])
    
    try:
        now = timezone.now()
        Vehicle.objects.create(
            plate_number=plate_number,
            brand=brand,
            model=model,
            color=random.choice(CONFIG["vehicles"]["colors"]),
            vehicle_type=random.choice(CONFIG["vehicles"]["types"]),
            user=user,
            visitor=visitor,
            register_date=datetime.date.today() - datetime.timedelta(days=random.randint(30, 2000)),
            created_at=now,
            updated_at=now
        )
    except Exception as e:
        person_info = f"用户ID {user.id}" if user else f"访客ID {visitor.id}"
        print(f"为 {person_info} 创建车辆失败: {e}")

def create_vehicles():
    """为部分企业员工和访客创建车辆信息"""
    print("\n创建车辆数据...")

    # 为企业员工生成车辆
    employee_profiles = CompanyEmployeeProfile.objects.select_related('user').all()
    if employee_profiles:
        employees_to_get_cars = random.sample(
            list(employee_profiles),
            k=int(len(employee_profiles) * CONFIG["vehicles"]["company_employee_ratio"])
        )
        employee_vehicle_count = 0
        for profile in employees_to_get_cars:
            create_single_vehicle(user=profile.user)
            employee_vehicle_count += 1
        print(f"为 {employee_vehicle_count} 位企业员工创建了车辆。")
    else:
        print("没有企业员工，跳过创建员工车辆。")

    # 为访客生成车辆
    visitors = Visitor.objects.all()
    if visitors:
        visitors_to_get_cars = random.sample(
            list(visitors),
            k=int(len(visitors) * CONFIG["vehicles"]["visitor_ratio"])
        )
        visitor_vehicle_count = 0
        for visitor in visitors_to_get_cars:
            create_single_vehicle(visitor=visitor)
            visitor_vehicle_count += 1
        print(f"为 {visitor_vehicle_count} 位访客创建了车辆。")
    else:
        print("没有访客，跳过创建访客车辆。")

def clear_old_personnel_data():
    """清除所有与人员、公司、访客相关的数据"""
    print("--- 正在清除旧的人员相关数据... ---")
    # 注意删除顺序，从依赖最深的开始
    # 车辆和员工档案都关联了User，访客也可能关联User，所以先处理这些
    Vehicle.objects.all().delete()
    ParkEmployeeProfile.objects.all().delete()
    CompanyEmployeeProfile.objects.all().delete()
    Visitor.objects.all().delete()
    Department.objects.all().delete()
    # 公司和用户是顶层，最后删除
    Company.objects.all().delete()
    # 删除所有用户，后续会在创建函数中重新生成管理员
    User.objects.all().delete()
    print("旧的人员、公司、部门、访客和车辆数据已清除。")

@transaction.atomic
def create_personnel_data():
    """创建所有人员、公司、访客等核心数据"""
    print("--- 开始创建人员相关数据... ---")
    
    # 创建系统管理员
    admin_user = create_admin_user()
    
    # 创建物业公司及其部门和员工
    property_company = create_company(CONFIG["property_company"]["type"])
    create_departments_and_employees(property_company, CONFIG["property_company"]["departments"])
    
    # 创建企业公司及其部门和员工
    companies = []
    for i in range(CONFIG["companies"]["count"]):
        company_type = random.choice(CONFIG["companies"]["types"])
        company = create_company(company_type)
        companies.append(company)
        create_departments_and_employees(company, CONFIG["company_departments"])
    
    # 创建访客
    create_visitors(companies)

    # 创建车辆
    create_vehicles()
    
    print("\n人员数据生成完成！")
    print_statistics()

def create_admin_user():
    """创建或获取系统管理员用户"""
    print("创建系统管理员...")
    
    try:
        admin_user = User.objects.filter(username='admin').first()
        if not admin_user:
            now = timezone.now()
            admin_user = User(
                username='admin',
                password=CONFIG["password"],
                phone='13800138000',
                email='admin@smartpark.com',
                register_time=now,
                status=1,
                created_at=now,
                updated_at=now
            )
            admin_user.save()
            
            # 创建管理员档案
            admin_profile = ParkEmployeeProfile(
                user=admin_user,
                name='系统管理员',
                gender='M',
                id_card=generate_id_card(),
                employee_no='P001',
                department='管理部',
                employee_type='管理员',
                hire_date=datetime.date.today() - datetime.timedelta(days=random.randint(30, 365)),
                created_at=now,
                updated_at=now
            )
            admin_profile.save()
            print("系统管理员创建成功")
        else:
            print("系统管理员已存在")
        
        return admin_user
    except Exception as e:
        print(f"创建系统管理员失败: {e}")
        return None

def create_company(company_type):
    """创建公司"""
    company_name = generate_company_name(company_type)
    credit_code = f"91{random.randint(100000, 999999)}MA{random.choice('ABCDEFGHIJKLMNPQRSTUVWXYZ')}{random.randint(10000, 99999)}{random.choice('0123456789ABCDEFGHJKLMNPQRTUWXY')}"
    
    try:
        now = timezone.now()
        company = Company(
            company_type=company_type,
            company_name=company_name,
            credit_code=credit_code,
            contact_phone=generate_phone(),
            entry_date=datetime.date.today() - datetime.timedelta(days=random.randint(1, 730)),
            created_at=now,
            updated_at=now
        )
        company.save()
        print(f"创建{company_type} - {company_name} 成功")
        return company
    except IntegrityError:
        # 如果信用代码重复，重新生成
        return create_company(company_type)
    except Exception as e:
        print(f"创建公司失败: {e}")
        return None

def create_departments_and_employees(company, department_names):
    """创建部门和员工"""
    if company is None:
        print("错误：公司对象为空，无法创建部门和员工")
        return []
        
    print(f"为 {company.company_name} 创建部门和员工...")
    
    departments = []
    legal_representative_created = False
    
    for dept_name in department_names:
        # 创建部门
        dept_code = f"D{company.company_id:02d}{department_names.index(dept_name) + 1:02d}"
        now = timezone.now()
        department = Department(
            department_name=dept_name,
            department_code=dept_code,
            company=company,
            description=f"负责{dept_name}相关工作",
            created_at=now,
            updated_at=now
        )
        department.save()
        departments.append(department)
        
        # 创建部门经理和员工
        for i in range(CONFIG["employees_per_department"]):
            is_manager = (i == 0)  # 第一个员工为部门经理
            is_legal_rep = not legal_representative_created and is_manager and department_names.index(dept_name) == 0
            
            if is_legal_rep:
                legal_representative_created = True
            
            create_employee(company, dept_name, is_manager, is_legal_rep)
    
    # 更新公司法人代表信息
    if company.legal_representative_user_id:
        print(f"为 {company.company_name} 设置法人代表成功")
    else:
        print(f"警告: {company.company_name} 未设置法人代表")
    
    return departments

def create_employee(company, department_name, is_manager=False, is_legal_rep=False):
    """创建员工"""
    name = generate_name()
    
    # 新的用户名生成逻辑
    # 1. 将中文名转换为拼音
    pinyin_list = pinyin(name, style=Style.NORMAL)
    username_base = ''.join(item[0] for item in pinyin_list)
    
    # 2. 添加随机数字后缀
    username = f"{username_base}{random.randint(10, 999)}"

    # 3. 处理用户名可能重复的情况
    while User.objects.filter(username=username).exists():
        username = f"{username_base}{random.randint(10, 999)}"
    
    position = "经理" if is_manager else random.choice(["主管", "专员", "助理", "工程师", "分析师", "顾问"])
    
    try:
        # 创建用户
        now = timezone.now()
        user = User(
            username=username,
            password=CONFIG["password"],
            phone=generate_phone(),
            email=generate_email(username),
            register_time=now,
            status=1,
            created_at=now,
            updated_at=now
        )
        user.save()
        
        # 创建员工档案
        if company.company_type == "物业公司":
            # 物业公司员工
            employee_type = department_name.replace("部", "工")
            if department_name == "管理部":
                employee_type = "管理员"
            elif department_name == "后勤部":
                employee_type = "送水工"
            
            employee = ParkEmployeeProfile(
                user=user,
                name=name,
                gender=random.choice(['M', 'F']),
                id_card=generate_id_card(),
                employee_no=f"P{random.randint(100, 999)}",
                department=department_name,
                employee_type=employee_type,
                hire_date=datetime.date.today() - datetime.timedelta(days=random.randint(1, 730)),
                created_at=now,
                updated_at=now
            )
            employee.save()
        else:
            # 企业员工
            employee = CompanyEmployeeProfile(
                user=user,
                company=company,
                name=name,
                gender=random.choice(['M', 'F']),
                id_card=generate_id_card(),
                employee_no=f"E{company.company_id:02d}{random.randint(100, 999)}",
                department=department_name,
                position=position,
                is_legal_representative=is_legal_rep,
                is_department_manager=is_manager,
                created_at=now,
                updated_at=now
            )
            employee.save()
            
            # 如果是法人代表，更新公司信息
            if is_legal_rep:
                company.legal_representative_user = user
                company.save()
        
        employee_type = "物业员工" if company.company_type == "物业公司" else "企业员工"
        position_text = f"({position})" if position else ""
        legal_text = "(法人代表)" if is_legal_rep else ""
        print(f"创建{employee_type}: {name} - {department_name}{position_text}{legal_text}")
        
        return user
    except Exception as e:
        print(f"创建员工失败: {e}")
        return None

def create_visitors(companies):
    """创建访客档案"""
    print(f"\n创建访客档案...")
    created_count = 0
    for i in range(CONFIG["visitors"]["count"]):
        try:
            name = generate_name()
            phone = generate_phone()
            id_card = generate_id_card()
            
            # 避免因唯一约束（电话、身份证）创建失败
            if Visitor.objects.filter(phone=phone).exists() or Visitor.objects.filter(id_card=id_card).exists():
                continue

            now = timezone.now()
            Visitor.objects.create(
                name=name,
                gender=random.choice(['M', 'F']),
                id_card=id_card,
                phone=phone,
                created_at=now,
                updated_at=now
            )
            created_count += 1
        except IntegrityError:
            # 以防万一的并发冲突
            continue
        except Exception as e:
            # 捕获其他可能的错误
            print(f"创建访客档案失败: {e}")
            
    print(f"成功创建 {created_count} 条访客档案。")

def print_statistics():
    """打印数据统计信息"""
    print("\n=== 数据统计 ===")
    print(f"用户总数: {User.objects.count()}")
    print(f"企业总数: {Company.objects.count()}")
    print(f"部门总数: {Department.objects.count()}")
    print(f"物业员工: {ParkEmployeeProfile.objects.count()}")
    print(f"企业员工: {CompanyEmployeeProfile.objects.count()}")
    print(f"访客总数: {Visitor.objects.count()}")
    print(f"车辆总数: {Vehicle.objects.count()}")
    
    # 按公司类型统计
    companies = Company.objects.all()
    company_types = {}
    for company in companies:
        if company.company_type not in company_types:
            company_types[company.company_type] = 0
        company_types[company.company_type] += 1
    
    print("\n公司类型统计:")
    for company_type, count in company_types.items():
        print(f"- {company_type}: {count}家")
    
    # 打印每个公司的员工数量
    print("\n各公司员工数量:")
    for company in companies:
        employee_count = CompanyEmployeeProfile.objects.filter(company=company).count()
        print(f"- {company.company_name}: {employee_count}人")

if __name__ == "__main__":
    """脚本独立执行时的入口"""
    # 独立执行时，先清理后创建
    clear_old_personnel_data()
    create_personnel_data() 